import React, { useMemo, useState, useCallback } from 'react';
import { createEditor, Descendant, Editor, Transforms, Element as SlateElement, BaseEditor } from 'slate';
import { Slate, Editable, withReact, useSlate, ReactEditor } from 'slate-react';
import { withHistory, HistoryEditor } from 'slate-history';
import { Card, Typography, Button, Space } from 'antd';
import { BoldOutlined, ItalicOutlined, UnderlineOutlined } from '@ant-design/icons';

const { Title, Paragraph } = Typography;

// 扩展 Slate 类型
declare module 'slate' {
  interface CustomTypes {
    Editor: BaseEditor & ReactEditor & HistoryEditor
    Element: {
      type: 'paragraph'
      children: CustomText[]
    }
    Text: {
      text: string
      bold?: boolean
      italic?: boolean
      underline?: boolean
    }
  }
}

type CustomText = {
  text: string
  bold?: boolean
  italic?: boolean
  underline?: boolean
}

type CustomElement = {
  type: 'paragraph'
  children: CustomText[]
}

const initialValue: Descendant[] = [
  {
    type: 'paragraph',
    children: [{ text: '这是 Slate 编辑器的初始内容。' }],
  } as CustomElement,
  {
    type: 'paragraph',
    children: [
      { text: 'Slate 是一个' },
      { text: '完全可定制', bold: true },
      { text: '的富文本编辑器框架。' },
    ],
  } as CustomElement,
];

const CustomEditor = {
  isBoldMarkActive(editor: Editor) {
    const marks = Editor.marks(editor);
    return marks ? marks.bold === true : false;
  },

  isItalicMarkActive(editor: Editor) {
    const marks = Editor.marks(editor);
    return marks ? marks.italic === true : false;
  },

  isUnderlineMarkActive(editor: Editor) {
    const marks = Editor.marks(editor);
    return marks ? marks.underline === true : false;
  },

  toggleBoldMark(editor: Editor) {
    const isActive = CustomEditor.isBoldMarkActive(editor);
    if (isActive) {
      Editor.removeMark(editor, 'bold');
    } else {
      Editor.addMark(editor, 'bold', true);
    }
  },

  toggleItalicMark(editor: Editor) {
    const isActive = CustomEditor.isItalicMarkActive(editor);
    if (isActive) {
      Editor.removeMark(editor, 'italic');
    } else {
      Editor.addMark(editor, 'italic', true);
    }
  },

  toggleUnderlineMark(editor: Editor) {
    const isActive = CustomEditor.isUnderlineMarkActive(editor);
    if (isActive) {
      Editor.removeMark(editor, 'underline');
    } else {
      Editor.addMark(editor, 'underline', true);
    }
  },
};

const MarkButton = ({ format, icon }: { format: string; icon: React.ReactNode }) => {
  const editor = useSlate();
  
  const isActive = () => {
    switch (format) {
      case 'bold':
        return CustomEditor.isBoldMarkActive(editor);
      case 'italic':
        return CustomEditor.isItalicMarkActive(editor);
      case 'underline':
        return CustomEditor.isUnderlineMarkActive(editor);
      default:
        return false;
    }
  };

  const toggleMark = () => {
    switch (format) {
      case 'bold':
        CustomEditor.toggleBoldMark(editor);
        break;
      case 'italic':
        CustomEditor.toggleItalicMark(editor);
        break;
      case 'underline':
        CustomEditor.toggleUnderlineMark(editor);
        break;
    }
  };

  return (
    <Button
      type={isActive() ? 'primary' : 'default'}
      onClick={toggleMark}
      icon={icon}
    />
  );
};

const Leaf = ({ attributes, children, leaf }: any) => {
  if (leaf.bold) {
    children = <strong>{children}</strong>;
  }

  if (leaf.italic) {
    children = <em>{children}</em>;
  }

  if (leaf.underline) {
    children = <u>{children}</u>;
  }

  return <span {...attributes}>{children}</span>;
};

const Element = ({ attributes, children, element }: any) => {
  switch (element.type) {
    case 'paragraph':
      return <p {...attributes}>{children}</p>;
    default:
      return <div {...attributes}>{children}</div>;
  }
};

const SlatePage: React.FC = () => {
  const [value, setValue] = useState<Descendant[]>(initialValue);
  const editor = useMemo(() => withHistory(withReact(createEditor())), []);

  const renderElement = useCallback((props: any) => <Element {...props} />, []);
  const renderLeaf = useCallback((props: any) => <Leaf {...props} />, []);

  const handleGetContent = () => {
    console.log('Slate content:', value);
  };

  return (
    <div style={{ padding: '24px' }}>
      <Card>
        <Title level={2}>Slate 富文本编辑器</Title>
        <Paragraph>
          Slate 是一个完全可定制的富文本编辑器框架，提供了强大的插件系统和灵活的数据模型。
        </Paragraph>
        
        <div style={{ marginTop: '20px' }}>
          <Slate editor={editor} initialValue={initialValue} onChange={setValue}>
            <Space style={{ marginBottom: '16px' }}>
              <MarkButton format="bold" icon={<BoldOutlined />} />
              <MarkButton format="italic" icon={<ItalicOutlined />} />
              <MarkButton format="underline" icon={<UnderlineOutlined />} />
            </Space>
            
            <div style={{ border: '1px solid #d9d9d9', borderRadius: '6px', padding: '12px', minHeight: '200px' }}>
              <Editable
                renderElement={renderElement}
                renderLeaf={renderLeaf}
                placeholder="输入内容..."
                spellCheck
                autoFocus
              />
            </div>
          </Slate>
        </div>
        
        <div style={{ marginTop: '20px' }}>
          <Button onClick={handleGetContent}>获取内容</Button>
        </div>
      </Card>
    </div>
  );
};

export default SlatePage;